package com.gin.no_gay_alliance.fragment.topic.page;

import static com.gin.no_gay_alliance.enums.MessageWhat.ON_SUCCESS_TOPIC_LIST_REQUEST;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.DividerItemDecoration;

import com.gin.jackson.utils.ObjectUtils;
import com.gin.nga.exception.NgaClientException;
import com.gin.nga.exception.NgaException;
import com.gin.nga.params.PageParam;
import com.gin.nga.params.thread.ColListParam;
import com.gin.nga.params.thread.ColSearchParam;
import com.gin.nga.params.thread.FavorParam;
import com.gin.nga.params.thread.ForumListParam;
import com.gin.nga.params.thread.ForumRecommendParam;
import com.gin.nga.params.thread.ForumSearchParam;
import com.gin.nga.params.thread.UserSearchParam;
import com.gin.nga.response.body.ThreadBody;
import com.gin.no_gay_alliance.R;
import com.gin.no_gay_alliance.adpter.topic.TopicItemAdapter;
import com.gin.no_gay_alliance.app.MyApplication;
import com.gin.no_gay_alliance.callback.Callback;
import com.gin.no_gay_alliance.databinding.DialogRecyclerViewTopicBinding;
import com.gin.no_gay_alliance.databinding.FragmentTopicPage2Binding;
import com.gin.no_gay_alliance.enums.MessageWhat;
import com.gin.no_gay_alliance.exception.RequireParamException;
import com.gin.no_gay_alliance.fragment.base.BaseBindingFragment;
import com.gin.no_gay_alliance.listener.MyScrollListener;
import com.gin.no_gay_alliance.manager.BlockDataManager;
import com.gin.no_gay_alliance.param.TopicListParam;
import com.gin.no_gay_alliance.utils.AlertDialogUtils;
import com.gin.no_gay_alliance.viewmodel.TopicItem;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

import okhttp3.Call;

/**
 * 主题列表分页
 *
 * @author : ginstone
 * @version : v1.0.0
 * @since : 2023/9/5 10:40
 **/
public class TopicPageFragment extends BaseBindingFragment<FragmentTopicPage2Binding> implements Callback<ThreadBody>, MyScrollListener.OnDraggingListener, MyScrollListener.OnDraggedListener {
    public static final String TAG = TopicPageFragment.class.getSimpleName();
    private static final String ARG_PARAM_KEY = TopicListParam.class.getName();
    private static final String ARG_PAGE_KEY = "page";
    private static final String ARG_CHECKBOX_KEY = "checkBox";
    /**
     * 是否显示复选框
     */
    boolean showCheckBox;
    /**
     * 参数
     */
    private TopicListParam param;
    /**
     * 当前页
     */
    private int page;
    /**
     * 主题项目适配器
     */
    private TopicItemAdapter adapter;
    private List<TopicItem> blockedTopics = new ArrayList<>();

    @Override
    protected void onCreateView() {
        adapter = new TopicItemAdapter(requireActivity());
        adapter.setShowCheckBox(showCheckBox);
        b.recyclerView.setAdapter(adapter);
        b.recyclerView.addItemDecoration(new DividerItemDecoration(requireActivity(), DividerItemDecoration.VERTICAL));
        MyScrollListener scrollListener = new MyScrollListener();
        scrollListener.setOnDraggingListener(this);
        scrollListener.setOnDraggedListener(this);
        b.recyclerView.addOnScrollListener(scrollListener);
        b.swipeRefreshLayout.setOnRefreshListener(() -> sendRequest(true));

        b.tvWarning.setVisibility(View.GONE);

        sendRequest(false);
    }


    /**
     * 获取和处理参数
     *
     * @param arguments 参数
     */
    @Override
    protected void handleArguments(Bundle arguments) {
        param = arguments.getParcelable(ARG_PARAM_KEY);
        page = arguments.getInt(ARG_PAGE_KEY, 0);
        showCheckBox = arguments.getBoolean(ARG_CHECKBOX_KEY, false);

        if (param == null || page <= 0) {
            throw new RequireParamException();
        }
    }

    /**
     * 创建选项菜单
     *
     * @param menu     菜单
     * @param inflater 渲染器
     */
    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.block_menu, menu);
    }

    /**
     * 点击选项按钮的操作
     *
     * @param item 选中的按钮
     * @return 是否消耗
     */
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        // 弹窗显示被屏蔽的主题列表
        if (item.getItemId() == R.id.menu_item_block) {
            DialogRecyclerViewTopicBinding bb = MyApplication.app.managerFactory.getViewBindingManager().getDialogView(DialogRecyclerViewTopicBinding.class, requireContext());
            bb.recyclerView.setAdapter(new TopicItemAdapter(requireContext(), blockedTopics));
            bb.recyclerView.addItemDecoration(new DividerItemDecoration(requireActivity(), DividerItemDecoration.VERTICAL));


            AlertDialog dialog = AlertDialogUtils.showConfirm(requireContext(), getString(R.string.blocked_topics), null, bb.getRoot(), null);
            dialog.setOnDismissListener(d -> {
                // 关闭时移除弹窗
                Log.d(TAG, "onOptionsItemSelected: 关闭时移除弹窗");
                ViewGroup parent = (ViewGroup) bb.getRoot().getParent();
                parent.removeView(bb.getRoot());
            });

            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onPrepareOptionsMenu(@NonNull Menu menu) {
        super.onPrepareOptionsMenu(menu);

        MenuItem menuItem = menu.findItem(R.id.menu_item_block);
        if (menuItem != null) {
            menuItem.setVisible(!ObjectUtils.isEmpty(blockedTopics));
            menuItem.setTitle(String.format(Locale.CHINA, "屏蔽 (%d)", blockedTopics.size()));
        }
    }

    /**
     * 发送请求
     *
     * @param ignoreCache 是否忽略缓存
     */
    public void sendRequest(boolean ignoreCache) {
        PageParam requestParam;
        switch (param.type) {
            case FORUM_LIST:
                requestParam = new ForumListParam(Long.parseLong(param.forumId), page, null);
                break;
            case COL_LIST:
                requestParam = new ColListParam(param.colTid, page, null);
                break;
            case FAVOR:
                requestParam = new FavorParam(param.folderId, page);
                break;
            case COL_SEARCH:
                requestParam = new ColSearchParam(param.colTid, param.keyword, page, param.searchContent, param.recommendOnly);
                break;
            case FORUM_SEARCH:
                List<Long> forumId = Arrays.stream(param.forumId.split(",")).map(Long::parseLong).collect(Collectors.toList());
                requestParam = new ForumSearchParam(param.keyword, page, param.searchContent, param.recommendOnly, forumId);
                break;
            case FORUM_RECOMMEND:
                requestParam = new ForumRecommendParam(Long.parseLong(param.forumId), page);
                break;
            case USER_SEARCH:
                Long fid = param.forumId != null ? Long.parseLong(param.forumId) : null;
                requestParam = new UserSearchParam(param.authorUid, page, fid, param.searchReply, param.recommendOnly);
                break;
            default:
                showWarning(new IOException("预期外的请求类型:" + param.type));
                return;
        }
        MyApplication.app.managerFactory.getTopicListManager().request(ignoreCache, requestParam, this);
    }

    /**
     * 请求成功回调
     *
     * @param data 数据
     */
    @Override
    public void onSuccess(ThreadBody data) {
        // 将消息抛出给父级
        getParentHandler().sendMessage(ON_SUCCESS_TOPIC_LIST_REQUEST, data);

        // 响应数据
        List<TopicItem> topicItems = data.getTopics().values().stream().map(TopicItem::new).collect(Collectors.toList());
        // 请求屏蔽设置
        MyApplication.app.managerFactory.getBlockDataManager().blockDataList(false, blockData -> {
            // 被屏蔽的主题
            blockedTopics = topicItems.stream().filter(i -> BlockDataManager.isBlocked(blockData, i)).collect(Collectors.toList());
            if (!blockedTopics.isEmpty()) {
                Log.d(TAG, String.format("屏蔽了 %d 个主题", blockedTopics.size()));
            }

            // 正常主题
            List<TopicItem> topics = topicItems.stream().filter(i -> !BlockDataManager.isBlocked(blockData, i)).collect(Collectors.toList());
            // 渲染数据
            if (handler != null) {
                ui(() -> {
                    b.swipeRefreshLayout.setRefreshing(false);
                    b.tvWarning.setVisibility(View.GONE);
                    b.recyclerView.setVisibility(View.VISIBLE);
                    adapter.updateData(topics);
                });
            }
        });
    }

    /**
     * 请求之前执行的操作
     */
    @Override
    public void beforeRequest() {
        b.swipeRefreshLayout.setRefreshing(true);
    }

    /**
     * 请求失败回调(一般为网络访问错误)
     *
     * @param call call
     * @param e    错误
     */
    @Override
    public void onFailure(@NonNull Call call, @NonNull IOException e) {
        Callback.super.onFailure(call, e);
        showWarning(e);
    }

    /**
     * 处理Nga异常
     *
     * @param e 异常
     */
    @Override
    public void handleException(NgaException e) {
        Callback.super.handleException(e);
        showWarning(e);
    }

    /**
     * 正在拖动
     *
     * @param dx 目前x方向的总距离
     * @param dy 目前y方向的总距离
     */
    @Override
    public void onDragging(int dx, int dy) {
        // 拖动距离大于100时，锁定上级翻页
        if (Math.abs(dy) >= 10) {
            getParentHandler().sendEmptyMessage(MessageWhat.LOCK_VIEW_PAGER);
        }
    }

    /**
     * 拖动结束
     *
     * @param dx x方向的总距离
     * @param dy y方向的总距离
     */
    @Override
    public void onDragged(int dx, int dy) {
        // 拖动结束时解锁翻页
        getParentHandler().sendEmptyMessage(MessageWhat.UNLOCK_VIEW_PAGER);
    }

    /**
     * 显示报错提示，隐藏主题列表
     *
     * @param e 异常
     */
    private void showWarning(IOException e) {
        String msg = (e instanceof NgaClientException) ? ((NgaClientException) e).getReason().get(0) : e.getMessage();
        ui(() -> {
            b.swipeRefreshLayout.setRefreshing(false);
            b.tvWarning.setVisibility(View.VISIBLE);
            b.recyclerView.setVisibility(View.GONE);
            b.tvWarning.setText(msg);
        });
    }

    /**
     * 实例化
     *
     * @param param        参数
     * @param page         页数
     * @param showCheckBox 是否显示复选框
     * @return fragment
     */
    public static TopicPageFragment newInstance(@NonNull TopicListParam param, @IntRange(from = 1) int page, boolean showCheckBox) {
        TopicPageFragment fragment = new TopicPageFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARG_PARAM_KEY, param);
        args.putInt(ARG_PAGE_KEY, page);
        args.putBoolean(ARG_CHECKBOX_KEY, showCheckBox);
        fragment.setArguments(args);
        return fragment;
    }

    /**
     * 返回被选中的主题
     *
     * @return 返回被选中的主题
     */
    public List<TopicItem> getCheckedItem() {
        return adapter.getCheckedItem();
    }

    /**
     * 设置本页所有主题的选中状态
     *
     * @param isChecked 是否选中
     */
    @SuppressLint("NotifyDataSetChanged")
    public void setAllChecked(boolean isChecked) {
        adapter.setAllChecked(isChecked);
    }
}
